package io.springboot.jpa.examples.springbootjpaexamples.config.shiro;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Calendar;
import java.util.Date;

/**
 * @author yzc
 * @description JWT工具类，负责生成和验证Token
 * @date 2018/9/26
 */
public class JwtUtils {

    private static final Algorithm algorithm;

    static {
        algorithm = Algorithm.HMAC256("mnJ0iLCJwZXJtaXNzaW9ucyI6WyJjZXJ0cy");
    }

    public static String createToken(String subject, String[] roles, String[] permissions) {
        Date issuedAt = new Date();
        Date expiresAt = new Date(issuedAt.getTime() + 30 * 60 * 1000);
        try {
            String jwt = JWT.create().withIssuer("issuer")
                    .withSubject(subject)
                    .withIssuedAt(issuedAt)
                    .withExpiresAt(expiresAt)
                    .withArrayClaim("roles", roles)
                    .withArrayClaim("permissions", permissions).sign(algorithm);
            return jwt;
        } catch (IllegalArgumentException e) {
        } catch (JWTCreationException e) {
        }
        return null;
    }

    public static boolean verify(String token) {
        try {
            JWT.require(algorithm).build().verify(token).getSignature();
            return true;
        } catch (JWTVerificationException e) {
            return false;
        }
    }

    public static String getSubject(String token) {
        try {
            DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
            return decodedJWT.getSubject();
        } catch (JWTVerificationException e) {
        }
        return null;
    }

    public static boolean isExpired(String token) {
        try {
            DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
            Date now = new Date();
            Date expiresAt = decodedJWT.getExpiresAt();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            return calendar.after(expiresAt);
        } catch (JWTVerificationException e) {
        }
        return false;
    }

    public static String[] getRoles(String token) {
        return getStringArrayClaim(token, "roles");
    }

    private static String[] getStringArrayClaim(String token, String name) {
        try {
            DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
            Claim rolesClaim = decodedJWT.getClaim(name);
            String[] roles = rolesClaim.asArray(String.class);
            return roles;
        } catch (JWTVerificationException e) {
        }
        return null;
    }

    public static String[] getPermissions(String token) {
        return getStringArrayClaim(token, "permissions");
    }
}
